package wxminipro

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"encoding/json"
	"errors"

	"gitee.com/yxd1990/golang-common/utils"
)

type WxMaUserInfo struct {
	OpenId    string `json:"openId"`
	NickName  string `json:"nickName"`
	Gender    int8   `json:"gender"`
	Language  string `json:"language"`
	City      string `json:"city"`
	Province  string `json:"province"`
	Country   string `json:"country"`
	AvatarUrl string `json:"avatarUrl"`
	UnionId   string `json:"unionId"`
}

func CheckUserInfoSignature(sessionKey, rawData, signature string) bool {
	return utils.GetSha1Value(rawData+sessionKey) == signature
}

func GetUserInfo(sessionKey, encryptedData, ivStr string) (userInfo *WxMaUserInfo, err error) {
	var decodeBytes []byte
	decodeBytes, err = base64.StdEncoding.DecodeString(encryptedData)
	if err != nil {
		return
	}
	var sessionKeyBytes []byte
	sessionKeyBytes, err = base64.StdEncoding.DecodeString(sessionKey)
	if err != nil {
		return
	}
	var ivBytes []byte
	ivBytes, err = base64.StdEncoding.DecodeString(ivStr)
	if err != nil {
		return
	}
	var dataBytes []byte
	dataBytes, err = AesCBCDncrypt(decodeBytes, sessionKeyBytes, ivBytes)
	if err != nil {
		return
	}
	userInfo = &WxMaUserInfo{}
	err = json.Unmarshal(dataBytes, userInfo)
	return
}

// 解密
func AesCBCDncrypt(encryptData, key, iv []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	if len(encryptData) < blockSize {
		return nil, errors.New("ciphertext too short")
	}
	if len(encryptData)%blockSize != 0 {
		return nil, errors.New("ciphertext is not a multiple of the block size")
	}
	mode := cipher.NewCBCDecrypter(block, iv)
	mode.CryptBlocks(encryptData, encryptData)
	// 解填充
	encryptData = PKCS7UnPadding(encryptData)
	return encryptData, nil
}

//去除填充
func PKCS7UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}
